package com.sx.export.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.sx.export.Utils.CustomCellWriteWidthConfig;
import com.sx.export.Utils.SplitZipUtil;
import com.sx.export.dao.IUserDao;
import com.sx.export.domain.po.User;
import com.sx.export.service.ExportExcelService;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.ibatis.cursor.Cursor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;

@Service
public class ExportExcelServiceImpl implements ExportExcelService {
    public static Integer USER_EXPORT_NUM = 100000;
    private final Object lock = new Object();

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    @Autowired
    private IUserDao userDao;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String exportExcelSignleThead() {
        Cursor<User> users = userDao.getAllUser();
        int i = 1;
        int j = 10;
        List<User> userList = new ArrayList<>();
        for (User user : users){
            if (i % USER_EXPORT_NUM == 0){
                exportExcel(userList, "D:\\test\\user" + j + ".xlsx");
                userList.clear();
                j++;
            }else {
                userList.add(user);
            }
            i++;
        }
        return "";
    }

    @Override
    public String exportExcelMultThead() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>(User.class);
        Long l = userDao.selectCount(queryWrapper);
        List<Future> futureList = new ArrayList<>();
        for(int i = 0; i < l/USER_EXPORT_NUM; i++){

            final int j = i;
            ExportExcelMultThread ExportExcelMultThread = new ExportExcelMultThread("D:\\test\\user" + j + ".xlsx",0,i);
            Future<?> submit = threadPoolExecutor.submit(ExportExcelMultThread);
//            Future<?> submit = threadPoolExecutor.submit(() -> {
//                exportExcel(users, "D:\\test\\user" + j + ".xlsx");
//            });
            futureList.add(submit);
//            exportExcel(users,"D:\\user" + j + ".xlsx");
//            break;
        }
        futureList.forEach(e -> {
            try {
                Object o = e.get();
                System.out.println("1");
            } catch (InterruptedException ex) {
                throw new RuntimeException(ex);
            } catch (ExecutionException ex) {
                throw new RuntimeException(ex);
            }
        });
        zipFile();
        return "";
    }

    @Override
    public String importSql() {
        for (int i =0; i < 1000; i++){
            List<User> users = new ArrayList<>();
            for (int j = 0; j < 1000; j++){
                User user = new User();
                user.setUserHead(String.valueOf(j));
                user.setUserNickname(String.valueOf(j));
                users.add(user);
            }
            userDao.insert(users);
            users.clear();
        }
        return "";
    }

    @Override
    public String synTest() {
        synchronized (lock){
            try {
                Thread.sleep(10000);
                System.out.println(System.currentTimeMillis());
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("1");
        };
        return "";
    }

    public boolean exportExcel(List<User> users, String fileName){
        EasyExcel.write(fileName, User.class).sheet(0).registerWriteHandler(new CustomCellWriteWidthConfig()).doWrite(users);
        return true;
    }

    public void zipFile() {
        String srcFilePath = "D:\\test"; // 大文件路径
        String destDir = "D:\\test1"; // 分卷压缩文件的输出目录
        try {
            SplitZipUtil.start(srcFilePath, destDir);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    class ExportExcelMultThread implements Callable<Boolean> {

//        private List<User> users;
        private String fileName;
        private int count = 0;
        private int num;

        @Override
        public Boolean call() throws Exception {
            List<User> users = userDao.selectList(new QueryWrapper<>(User.class).last("limit " + USER_EXPORT_NUM * num + ", " + USER_EXPORT_NUM));
            try {
                EasyExcel.write(fileName, User.class).sheet(0).registerWriteHandler(new CustomCellWriteWidthConfig()).doWrite(users);
            }catch (Exception e){
                if (count < 3 ){
                    call();
                }else {
                    return false;
                }

            }
            return true;
        }
    }
}
